/**
 * ReportGear(2011)
 */
package com.reportgear.report.model;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;

import com.reportgear.report.model.cell.Cell;
import com.reportgear.report.model.cell.DefaultCell;

/**
 * 单元格网格，统一管理模型中的单元格
 * 
 * @version 1.0 2011-3-11
 * @author <a herf="lexloo@gmail.com">lexloo</a>
 * @since Report 1.0
 */
class CellGrid {
	private List<Row> rowList;

	/**
	 * 构造器,包含一个单元格
	 */
	public CellGrid() {
		this.rowList = new ArrayList<Row>();
	}

	/**
	 * 获取行总数
	 * 
	 * @return 行总数
	 */
	public int getRowCount() {
		return this.rowList.size();
	}

	/**
	 * 获取列总数
	 * 
	 * @return 列总数
	 */
	public int getColumnCount() {
		return this.rowList.size() == 0 ? 0 : this.rowList.get(0).size();
	}

	/**
	 * 获取指定单元格
	 * 
	 * @param column
	 *            列 0 based
	 * @param row
	 *            行 0 based
	 * @return 单元格
	 */
	public Cell getCell(int column, int row) {
		return this.rowList.get(row).get(column);
	}

	/**
	 * 设置指定单元格的值
	 * 
	 * @param column
	 *            列 0 based
	 * @param row
	 *            行 0 based
	 * @param value
	 *            值
	 */
	public void setCellValue(int column, int row, Object value) {
		Cell cell = this.getCell(column, row);

		cell.setValue(value);
	}

	/**
	 * 清除Cell的值
	 * 
	 * @param column
	 *            行 0 based
	 * @param row
	 *            列 0 based
	 */
	public void clearCell(int column, int row) {
		this.getCell(column, row).clear();
	}

	/**
	 * @return 单元格迭代器
	 */
	public Iterator<Cell> cellIterator() {
		return new CellIterator();
	}

	/**
	 * Cell交叉集
	 * 
	 * @param columnFrom
	 *            开始行 0 based
	 * @param rowFrom
	 *            开始列 0 based
	 * @param columnSpan
	 *            列跨度
	 * @param rowSpan
	 *            行跨度
	 * @return 迭代器
	 */
	public Iterator<Cell> intersect(int columnFrom, int rowFrom, int columnSpan, int rowSpan) {
		return new IntersectIterator(columnFrom, rowFrom, columnSpan, rowSpan);
	}

	/**
	 * CellGrid列迭代器
	 * 
	 * @param column
	 *            列 0 based
	 * @return 列迭代器
	 */
	public Iterator<Cell> getColumn(int column) {
		return new ColumnIterator(column);
	}

	/**
	 * CellGrid行迭代器
	 * 
	 * @param row
	 *            行 0 based
	 * @return 行迭代器
	 */
	public Iterator<Cell> getRow(int row) {
		return new RowIterator(row);
	}

	/**
	 * 获取包含指定类型对象的单元格迭代器
	 * 
	 * @param clazz
	 *            元素类
	 * @return 迭代器
	 */
	public Iterator<Cell> getCellsByElementClass(Class<?> clazz) {
		return new CellElementIterator(clazz);
	}

	/**
	 * 增加行
	 * 
	 * @param index
	 *            索引
	 */
	void addRow(int index) {
		// 偏移Index以后的所有Row的Index
		for (int i = index, size = this.getRowCount(); i < size; i++) {
			Iterator<Cell> cells = this.getRow(i);
			while (cells.hasNext()) {
				Cell cell = cells.next();
				cell.setRow(cell.getRow() + 1);
			}
		}
		
		this.rowList.add(index, new Row(index, this.getColumnCount()));
	}

	/**
	 * 增加列
	 * 
	 * @param index
	 *            索引
	 */
	void addColumn(int index) {
		// 偏移Index以后所有Column的Index
		for (int i = index, size = this.getColumnCount(); i < size; i++) {
			Iterator<Cell> cells = this.getColumn(i);
			while (cells.hasNext()) {
				Cell cell = cells.next();
				cell.setColumn(cell.getColumn() + 1);
			}
		}

		for (int i = 0, size = this.rowList.size(); i < size; i++) {
			Row r = this.rowList.get(i);
			r.add(index, new DefaultCell(index, i));
		}
	}

	/**
	 * 删除指定行
	 * 
	 * @param index
	 *            索引
	 */
	void deleteRow(int index) {
		for (int i = index + 1, size = this.getRowCount(); i < size; i++) {
			Iterator<Cell> cells = this.getRow(i);
			while (cells.hasNext()) {
				Cell cell = cells.next();
				cell.setRow(cell.getRow() - 1);
			}
		}

		this.rowList.remove(index);
	}

	/**
	 * 删除指定列
	 * 
	 * @param index
	 *            索引
	 */
	void deleteColumn(int index) {
		for (int i = index + 1, size = this.getColumnCount(); i < size; i++) {
			Iterator<Cell> cells = this.getColumn(i);
			while (cells.hasNext()) {
				Cell cell = cells.next();
				cell.setColumn(cell.getColumn() - 1);
			}
		}
		for (int j = 0; j < this.getRowCount(); j++) {
			this.rowList.get(j).remove(index);
		}
	}

	@Override
	public CellGrid clone() {
		CellGrid cloned = new CellGrid();
		cloned.rowList = new ArrayList<Row>();
		for (Row r : this.rowList) {
			cloned.rowList.add(r.clone());
		}

		return cloned;
	}

	/**
	 * 列迭代器
	 * 
	 */
	private class ColumnIterator implements Iterator<Cell> {

		private int columnIndex;
		private int currRow = -1;
		private int nextRow = 0;
		private Cell next;

		ColumnIterator(int columnIndex) {
			this.columnIndex = columnIndex;
			findNext();
		}

		public boolean hasNext() {
			return (this.next != null);
		}

		public Cell next() {
			if (!hasNext()) {
				throw new NoSuchElementException("已到最后一个元素");
			}
			Cell cell = this.next;
			findNext();
			return cell;
		}

		public void remove() {
			throw new UnsupportedOperationException("不支持");
		}

		private void findNext() {
			Cell cell;
			do {
				if (this.nextRow >= rowList.size()) {
					this.next = null;
					return;
				}
				cell = rowList.get(this.nextRow).get(this.columnIndex);
				this.currRow = this.nextRow;
				this.nextRow += 1;
			} while ((cell == null) || (cell.getColumn() != this.columnIndex) || (cell.getRow() != this.currRow));
			this.next = cell;
			return;
		}
	}

	/**
	 * 行迭代器
	 */
	private class RowIterator implements Iterator<Cell> {

		private int rowIndex;
		private int currColumn = -1;
		private int nextColumn = 0;
		private Cell next;

		public RowIterator(int rowIndex) {
			this.rowIndex = rowIndex;
			findNext();
		}

		public boolean hasNext() {
			return (this.next != null);
		}

		public Cell next() {
			if (!(hasNext())) {
				throw new NoSuchElementException("已到最后一个元素");
			}
			Cell cell = this.next;
			findNext();
			return cell;
		}

		public void remove() {
			throw new UnsupportedOperationException("不支持");
		}

		private void findNext() {
			Cell cell;
			if ((this.rowIndex < 0) || (this.rowIndex >= rowList.size())) {
				return;
			}
			Row row = rowList.get(this.rowIndex);
			int size = row.size();
			do {
				if (this.nextColumn >= size) {
					this.next = null;
					return;
				}
				cell = row.get(this.nextColumn);
				this.currColumn = this.nextColumn;
				this.nextColumn += 1;
			} while ((cell == null) || (cell.getColumn() != this.currColumn) || (cell.getRow() != this.rowIndex));
			this.next = cell;
			return;
		}
	}

	/**
	 * 单元格迭代器
	 */
	private class CellIterator implements Iterator<Cell> {
		private int nextRow = 0;
		private int nextCol = -1;
		private Cell next = null;

		CellIterator() {
			findNext();
		}

		public boolean hasNext() {
			return (this.next != null);
		}

		public Cell next() {
			if (!hasNext()) {
				throw new NoSuchElementException("已到最后一个元素");
			}
			Cell cell = this.next;

			findNext();
			return cell;
		}

		public void remove() {
			throw new UnsupportedOperationException("不支持");
		}

		private void findNext() {
			int i = this.nextCol + 1;
			for (int j = this.nextRow, size = rowList.size(); j < size; j++) {
				Row row = rowList.get(j);
				while (i < row.size()) {
					Cell cell = row.get(i);
					if ((cell != null) && (cell.getColumn() == i) && (cell.getRow() == j)) {
						this.nextRow = j;
						this.nextCol = i;
						this.next = cell;
						return;
					}
					++i;
				}
				i = 0;
			}
			this.next = null;
		}
	}

	/**
	 * 交叉单元迭代器
	 */
	private class IntersectIterator implements Iterator<Cell> {

		private int columnFrom;
		private int columnTo;
		private int rowFrom;
		private int rowTo;
		private int currRow;
		private int currColumn;
		private int nextRow;
		private int nextColumn;
		private Cell next;

		private IntersectIterator(int columnFrom, int rowFrom, int columnTo, int rowTo) {
			this.next = null;
			this.columnFrom = Math.max(columnFrom, 0);
			this.columnTo = Math.min(columnFrom + columnTo - 1, getColumnCount() - 1);
			this.rowFrom = Math.max(rowFrom, 0);
			this.rowTo = Math.min(rowFrom + rowTo - 1, getRowCount() - 1);
			this.currRow = -1;
			this.currColumn = -1;
			this.nextRow = this.rowFrom;
			this.nextColumn = (this.columnFrom - 1);
			findNext();
		}

		public boolean hasNext() {
			return (this.next != null);
		}

		public Cell next() {
			if (!(hasNext())) {
				throw new NoSuchElementException("已到最后一个元素");
			}
			Cell cell = this.next;
			this.currColumn = this.nextColumn;
			this.currRow = this.nextRow;
			findNext();
			return cell;
		}

		public void remove() {
			throw new UnsupportedOperationException("不支持");
		}

		private void findNext() {
			if (this.currRow == this.rowTo) {
				if (this.currColumn == this.columnTo) {
					this.next = null;
				} else {
					this.nextColumn += 1;
					this.next = getCell(this.nextColumn, this.nextRow);
				}
			} else {
				if (this.currColumn == this.columnTo) {
					this.nextColumn = this.columnFrom;
					this.nextRow += 1;
					this.next = getCell(this.nextColumn, this.nextRow);
				} else {
					this.nextColumn += 1;
					this.next = getCell(this.nextColumn, this.nextRow);
				}
			}
		}
	}

	/**
	 * 单元格值为制定对象的单元格迭代器
	 */
	private class CellElementIterator implements Iterator<Cell> {
		private int nextRow = 0;
		private int nextCol = -1;
		private Cell next = null;
		private Class<?> valueClass;

		CellElementIterator(Class<?> valueClass) {
			this.valueClass = valueClass;
			findNext();
		}

		public boolean hasNext() {
			return (this.next != null);
		}

		public Cell next() {
			if (!(hasNext())) {
				throw new NoSuchElementException("已到最后一个元素");
			}
			Cell cell = this.next;

			findNext();
			return cell;
		}

		public void remove() {
			throw new UnsupportedOperationException("不支持");
		}

		private void findNext() {
			int i = this.nextCol + 1;
			for (int j = this.nextRow, size = rowList.size(); j < size; j++) {
				Row row = rowList.get(j);
				while (i < row.size()) {
					Cell cell = row.get(i);
					if ((cell != null) && (cell.getValue() != null)) {
						if ((this.valueClass.isInstance(cell.getValue())) && (cell.getColumn() == i)
								&& (cell.getRow() == j)) {
							this.nextRow = j;
							this.nextCol = i;
							this.next = cell;
							return;
						}
					}
					i++;
				}
				i = 0;
			}
			this.next = null;
		}
	}

	/**
	 * 行元素
	 */
	private static class Row {
		private List<Cell> cells;

		private Row() {
			this.cells = new ArrayList<Cell>();
		}

		private Row(int row, int size) {
			this.cells = new ArrayList<Cell>(size);

			for (int i = 0; i < size; i++) {
				this.cells.add(new DefaultCell(i, row));
			}
		}

		public int size() {
			return this.cells.size();
		}

		public Cell get(int index) {
			return this.cells.get(index);
		}

		public void add(int index, Cell cell) {
			this.cells.add(index, cell);
		}

		public void remove(int index) {
			this.cells.remove(index);
		}

		@Override
		public Row clone() {
			Row row = new Row();
			for (Cell c : this.cells) {
				row.cells.add(c.clone());
			}

			return row;
		}
	}
}
